import { ref, Ref } from 'vue'

interface InitialValueType {
  x: number,
  y: number
}
interface OptionsType {
  type?: string,
  touch?: boolean,
  resetOnTouchEnds?: boolean,
  initialValue?: InitialValueType,
  window?: Window | HTMLElement,
  eventFilter?: Function
}
export default function useMouse(options: OptionsType = {
  type: 'page',
  touch: true,
  resetOnTouchEnds: false,
  initialValue: { x: 0, y: 0 },
  window: window,
  eventFilter: undefined
}):{ x: Ref<number>, y: Ref<number>, sourceType: Ref<string> } {
  const {
    type,
    touch,
    resetOnTouchEnds,
    initialValue,
    window,
    eventFilter,
  } = options

  const x = ref((<InitialValueType>initialValue).x)
  const y = ref((<InitialValueType>initialValue).y)
  const sourceType = ref('')

  const mouseHandler = (event: MouseEvent):void => {
    if (type === 'page') {
      x.value = event.pageX
      y.value = event.pageY
    }
    else if (type === 'client') {
      x.value = event.clientX
      y.value = event.clientY
    }
    else if (type === 'movement') {
      x.value = event.movementX
      y.value = event.movementY
    }
    sourceType.value = 'mouse'
  }
  const reset = () => {
    x.value = (<InitialValueType>initialValue).x
    y.value = (<InitialValueType>initialValue).y
  }
  const touchHandler = (event: TouchEvent) => {
    if (event.touches.length > 0) {
      const touch = event.touches[0]
      if (type === 'page') {
        x.value = touch.pageX
        y.value = touch.pageY
      }
      else if (type === 'client') {
        x.value = touch.clientX
        y.value = touch.clientY
      }
      sourceType.value = 'touch'
    }
  }

  const mouseHandlerWrapper = (event: Event):void => {
    eventFilter === undefined ? mouseHandler(<MouseEvent>event) : eventFilter(() => mouseHandler(<MouseEvent>event), {})
  }

  const touchHandlerWrapper = (event: Event):void => {
    eventFilter === undefined ? touchHandler(<TouchEvent>event) : eventFilter(() => touchHandler(<TouchEvent>event), {})
  }

  if (window) {
    window.addEventListener('mousemove', mouseHandlerWrapper, { passive: true })
    window.addEventListener('dragover', mouseHandlerWrapper, { passive: true })
    if (touch && type !== 'movement') {
      window.addEventListener('touchstart', touchHandlerWrapper, { passive: true })
      window.addEventListener('touchmove', touchHandlerWrapper, { passive: true })
      if (resetOnTouchEnds)
      window.addEventListener('touchend', reset, { passive: true })
    }
  }

  return {
    x,
    y,
    sourceType,
  }
}
